/**
 * @file communicate.c
 * @brief 双板通信核心实现文件
 *        包含双板通信数据结构体初始化、发送任务及接收处理函数，实现底盘板与云台板之间的实时数据交互
 * @author WeiFan Qiu (qiuweifan0523@faxmail.com)
 * @version 1.0
 * @date 2025-08-08
 * 
 * @copyright Copyright (c) 2025 邱伟凡
 * 
 * @par 修改日志:
 * - 2025-08-08: 初始版本创建，实现基础通信逻辑
 * 
 * @bug 待解决问题:
 * - 通信超时重传机制未完善
 */
#include "QWF_Ctrl.h"
/******************** 防止出错警告定义（编译时检查电路板类型配置） ******************/
#ifndef Circuit_Boards
	#error "Undefine 'Circuit_Boards'"  // 未定义电路板类型时报错
#endif
/**
 * @brief 双板通信发送接口
 */ 
#define send_data_communicate(data) Can_Send_Data(0x666,0,(uint8_t*)&data,&get_can_type(h,can2));
// 非单板模式时初始化通信结构体（双板通信场景）
#if Circuit_Boards!=Only_One
static __align(1) communicate_t Communicate={  // 通信数据结构体实例（1字节对齐）
.head={  // 上板（云台）相关数据
	.ctrl={  // 控制数据缓冲区
		.befor={.head=Ctrl_Befor_Data,.use=1,},  // 前半控制数据（头类型为Ctrl_Befor_Data，启用）
		.later={.head_1=Ctrl_Later_Data,.use=1,}  // 后半控制数据（头类型为Ctrl_Later_Data，启用）
	},
	.mode={  // 模式数据
		.head_1=Head_Mode_Data,.use=1,  // 头类型为Head_Mode_Data，启用
	},
	.vision={  // 视觉数据
	.head_1=Vision_Data,.use=1,  // 头类型为Vision_Data，启用
	},
	.need={  // 数据请求
		.head_1=Head_Need_Data,.use=1,  // 头类型为Head_Need_Data，启用
	},
},
.chassis={  // 底盘相关数据
	.need={  // 底盘数据请求
		.head_1=Chassis_Need_Data,.use=1,  // 头类型为Chassis_Need_Data，启用
	},	
	.judge={  // 裁判系统数据
		.head_1=Judge_Data,.use=1,  // 头类型为Judge_Data，启用
	},
},
};
communicate_t* communicate=&Communicate;  // 通信结构体全局指针

/**
 * @brief 双板通信发送任务（FreeRTOS任务）
 * @details 周期性（2ms）发送双板通信数据，根据当前通信ID选择发送内容
 *          支持底盘板（Chassis_Circuit_Boards）和云台板（Gimbal_Circuit_Boards）两种模式
 * @param argument 任务参数（未使用）
 */ 
void communicate_tx_task(void const * argument)
{
	static TickType_t xLastWakeTime;  // 任务唤醒时间记录
    const TickType_t xPeriod = pdMS_TO_TICKS(2); // 任务周期：2ms
    xLastWakeTime = xTaskGetTickCount();  // 初始化唤醒时间

	while(1){
//		#if Circuit_Boards==Chassis_Circuit_Boards
//			if(get_qwf_sys_tick()-communicate->head.ctrl.befor.online.tick >=1000){
//				communicate->id=Chassis_Need_Data;
//				communicate->chassis.need.data.e=Ctrl_Befor_Data;
//			}
//			else if(get_qwf_sys_tick()-communicate->head.ctrl.later.online.tick >=1000){
//				communicate->id=Chassis_Need_Data;
//				communicate->chassis.need.data.e=Ctrl_Later_Data;
//			}
//			else if(get_qwf_sys_tick()-communicate->head.mode.online.tick       >=1000){
//				communicate->id=Chassis_Need_Data;
//				communicate->chassis.need.data.e=Head_Mode_Data;				
//			}
//			else if(get_qwf_sys_tick()-communicate->head.vision.online.tick     >=1000){
//				communicate->id=Chassis_Need_Data;
//				communicate->chassis.need.data.e=Vision_Data;								
//			}
//		
//		#elif Circuit_Boards==Head_Circuit_Boards
//			if(get_qwf_sys_tick()-communicate->chassis.judge.online.tick >=1000){
//				communicate->id=Head_Need_Data;
//				communicate->head.need.data.e=Judge_Data;				
//			}
//			
//		#endif			
		switch((int)communicate->id){  // 根据当前通信ID选择发送数据类型
		#if Circuit_Boards==Chassis_Circuit_Boards  // 底盘板模式
			case Chassis_Need_Data:  // 发送底盘数据请求
				send_data_communicate(communicate->chassis.need); 					
				communicate->id=Judge_Data;  // 切换下一个ID为裁判系统数据
			break;
			case Judge_Data:  // 发送裁判系统数据
				send_data_communicate(communicate->chassis.judge);
				communicate->id=Judge_Data;  // 保持ID为裁判系统数据（循环发送）
			break;
			default:  // 默认发送裁判系统数据
				send_data_communicate(communicate->chassis.judge);
				communicate->id=Judge_Data;
		#elif Circuit_Boards==Head_Circuit_Boards  // 云台板模式
			case Head_Need_Data:  // 发送上板数据请求
				send_data_communicate(communicate->head.need); 							
				communicate->id=Ctrl_Later_Data;  // 切换下一个ID为后半控制数据			
			break;
			case Ctrl_Befor_Data:  // 发送前半控制数据
				communicate->head.ctrl.befor.type=ctrl->type;  // 同步遥控器类型
				communicate->head.ctrl.befor.mode=ctrl->mode;  // 同步控制模式
				send_data_communicate(communicate->head.ctrl.befor);
				communicate->id=Ctrl_Later_Data;  // 切换下一个ID为后半控制数据
			break;
			case Ctrl_Later_Data:  // 发送后半控制数据
				send_data_communicate(communicate->head.ctrl.later);
				communicate->id=Head_Mode_Data;  // 切换下一个ID为模式数据
			break;
			case Head_Mode_Data:  // 发送模式数据（云台/发弹/视觉模式）
				communicate->head.mode.data.str.vision=vision_mode;  	// 同步视觉模式
				communicate->head.mode.data.str.gimbal=gimbal_mode[now];  // 同步云台模式
				communicate->head.mode.data.str.shoot=shoot_mode[now];  // 同步发弹模式
				communicate->head.mode.data.str.use_fire_loop=head->part.shoot.fire.speed_loop.use;  // 同步射速闭环标志
				communicate->head.mode.data.str.use_vision_fire=vision->rx.use_fire_advice;  // 同步视觉触发发射标志
				send_data_communicate(communicate->head.mode);
				communicate->id=Vision_Data;  // 切换下一个ID为视觉数据
			break;
			case Vision_Data:  // 发送视觉数据（目标距离）
				communicate->head.vision.data.str.diatance=vision->rx.distance;  // 同步视觉目标距离
				send_data_communicate(communicate->head.vision);
				communicate->id=Ctrl_Befor_Data;  // 切换下一个ID为前半控制数据（循环）			
			break;
			default:  // 默认从控制前半数据开始循环
				send_data_communicate(communicate->head.ctrl.befor);
				communicate->id=Ctrl_Befor_Data;
			break;
		#endif	
		}
		vTaskDelayUntil(&xLastWakeTime, xPeriod);  // 等待下一个周期（严格周期性执行）
	}
}

/**
 * @brief 双板通信接收处理函数
 * @details 解析CAN接收的通信数据，根据数据头类型更新对应结构体字段，并同步系统状态
 * @param data 指向接收数据结构体（communicate_rx_t）的指针
 */
void comunicate_cal(communicate_rx_t* data)
{
	switch(data->head_1){  // 根据数据头类型分支处理
	#if Circuit_Boards==Chassis_Circuit_Boards  // 底盘板模式
		case Head_Need_Data:{  // 处理上板数据请求
			*(communicate_rx_t*)&communicate->head.need=*data;  // 更新需求数据结构体
			if(communicate->id>Head_Need_Data&&communicate->id<Chassis_Need_Data)  // 数据可信时更新通信ID
				communicate->id=communicate->head.need.data.e;
			qwf_state->communicate.online.tick=communicate->head.need.online.tick=qwf_state->sys_tick;  // 更新在线计时（防丢失）
		}break;
		case Ctrl_Befor_Data:{  // 处理前半控制数据
			*(communicate_rx_t*)&communicate->head.ctrl.befor=*data;  // 更新前半控制数据结构体
			ctrl->mode=(ctrl_mode_e)communicate->head.ctrl.befor.mode;  // 同步控制模式（遥控器/键鼠）
			ctrl->type=(ctrl_type_e)communicate->head.ctrl.befor.type;  // 同步遥控器类型（DT7/VT13）
			Ctrl_rx_func_chassis();  // 底盘控制数据接收回调（处理具体控制逻辑）
			switch((int)ctrl->type){  // 更新对应遥控器的在线状态
				case DT7:qwf_state->head.rc.dt7.online.tick=qwf_state->sys_tick;break;
				case VT13:qwf_state->head.rc.vt13.online.tick=qwf_state->sys_tick;break;				
			}	
			qwf_state->communicate.online.tick=communicate->head.ctrl.befor.online.tick=qwf_state->sys_tick;  // 更新通信在线计时
		}break;
		case Ctrl_Later_Data:{  // 处理后半控制数据
			*(communicate_rx_t*)&communicate->head.ctrl.later=*data;  // 更新后半控制数据结构体
			Ctrl_rx_func_chassis();  // 底盘控制数据接收回调
			qwf_state->communicate.online.tick=communicate->head.ctrl.later.online.tick=qwf_state->sys_tick;  // 更新通信在线计时
		}break;
		case Head_Mode_Data:{  // 处理模式数据
			*(communicate_rx_t*)&communicate->head.mode=*data;  // 更新模式数据结构体
			if(communicate->head.vision.data.str.head_ok==0)  // 视觉模块离线时禁用发射标志
				communicate->head.vision.data.str.fire=0;
			qwf_state->communicate.online.tick=communicate->head.mode.online.tick=qwf_state->sys_tick;  // 更新通信在线计时
		}break;
		case Vision_Data:{  // 处理视觉数据
			*(communicate_rx_t*)&communicate->head.vision=*data;  // 更新视觉数据结构体
			qwf_state->communicate.online.tick=communicate->head.vision.online.tick=qwf_state->sys_tick;  // 更新通信在线计时
		}break;		
	#elif Circuit_Boards==Head_Circuit_Boards  // 云台板模式
		case Chassis_Need_Data:  // 处理底盘数据请求
			*(communicate_rx_t*)&communicate->chassis.need=*data;  // 更新底盘需求数据结构体
			if(communicate->id>Chassis_Need_Data&&communicate->id<communicate_num)  // 数据可信时更新通信ID
				communicate->id=communicate->chassis.need.data.e;		
			qwf_state->communicate.online.tick=communicate->chassis.need.online.tick=qwf_state->sys_tick;  // 更新通信在线计时
		break;
		case Judge_Data:{  // 处理裁判系统数据
			*(communicate_rx_t*)&communicate->chassis.judge=*data;  // 更新裁判数据结构体
			my_team=communicate->chassis.judge.data.str.my_team;  // 同步己方队伍颜色
			qwf_state->chassis.judge.online.tick=qwf_state->sys_tick;  // 更新裁判系统在线计时
			qwf_state->communicate.online.tick=communicate->chassis.judge.online.tick=qwf_state->sys_tick;  // 更新通信在线计时
		}break;
	#endif	
	}
}
#endif
